"""与客户相关的视图"""

from rest_framework.views import APIView
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
# 导入分页
from rest_framework.pagination import PageNumberPagination
# 导入Q查询
from django.db.models import Q
# 导入模型
from sa.models import CustomerInfo
# 导入序列化器
from sa.serializers.customerSerializer import CustomerInfoSerializer

import logging

# 日志记录对象
logger = logging.getLogger('django')


# 创建分页类
class LargeResultsSetPagination(PageNumberPagination):
    # 定义了默认每页显示的记录数（即如果用户没有通过 size 参数指定每页大小，则默认每页显示 10 条）
    page_size = 10  # 默认每页显示多少条记录 10条
    page_size_query_param = 'size'  # 每页显示10条 前端控制每页显示条数的参数名（如参数 ?size=10）
    page_query_param = 'page'  # 表示请求第3页 前端发送的查询页码关键字名，默认为"page"（如参数 ?page=3, 第三页）
    max_page_size = 100  # 前端最多能设置的每页显示数量不能超过20条 限制用户通过 size 参数能设置的最大值

    """
    DRF 分页响应格式：
    {
        "count": 100,
        "next": "http://...?page=3",
        "previous": "http://...?page=1",
        "results": [...]
    }
    """


class CustomerInfoListGenericAPIView(GenericAPIView):
    """客户信息查询和新增"""
    # serializer_class, 指定序列化器类 拿到序列化器
    serializer_class = CustomerInfoSerializer
    # queryset  指明使用的数据查询集（数据来源）
    queryset = CustomerInfo.objects.all().order_by('-id')
    # 指定只有经过认证的用户才能访问该视图或视图集
    permission_classes = [IsAuthenticated]
    # 使用分页类 定义分页规则
    pagination_class = LargeResultsSetPagination

    def get(self, request):
        # 1.从类属性中获取查询集
        customer_list = self.get_queryset()  # 返回所有数据（未分页前的完整查询集）
        # request.query_params 获取 URL 查询参数
        search_query = request.query_params.get('search', None)
        if search_query:
            customer_list = customer_list.filter(
                Q(name__icontains=search_query) | Q(remark__icontains=search_query)
            )

        # 2.关键分页处理  对获得的查询集使用 paginate_queryset方法进行数据切片
        page_queryset = self.paginate_queryset(customer_list)  # 返回当前页的数据切片,也是一个查询集
        # 返回值说明：
        # - 如果请求包含分页参数（如 ?page=2）→ 返回当前页的切片数据（QuerySet 子集）
        # - 如果未分页（如无分页参数或 pagination_class=None）→ 返回 None
        if page_queryset is not None:
            # 3.分页成功时 创建序列化器对象 并返回带分页元数据的响应
            serializer = self.get_serializer(instance=page_queryset, many=True)
            # 返回值说明
            # return Response(data=serializer.data)
            # 使用 Response(serializer.data)  仅包含当前页数据[{...}, {...}]  丢失分页信息
            # 使用 self.get_paginated_response(serializer.data)
            # 标准分页格式 {count, next, previous, results}  前端可获取分页状态
            return self.get_paginated_response(data=serializer.data)
        else:
            # 4.未分页时：直接返回全部数据（普通响应）
            serializer = self.get_serializer(instance=customer_list, many=True)
            return Response(data=serializer.data)

    def post(self, request):
        """添加客户, 不允许只有 SA_User 角色的用户添加客户"""
        # values_list  只从数据库获取 name 字段，而不是整个 Role 对象
        # flat=True 只需要单个字段时，返回平面列表而不是元组列表
        role_name = request.user.roles.values_list('role_name', flat=True)
        if len(role_name) == 1 and role_name[0] == 'SA_User':
            return Response(data={"error": "普通用户不能新建客户"}, status=status.HTTP_403_FORBIDDEN)
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        logger.info(f"{request.user} 创建客户 {serializer.validated_data['name']} 成功")
        # print(serializer.validated_data)
        return Response(data=serializer.validated_data, status=status.HTTP_201_CREATED)


class CustomerInfoDetailGenericAPIView(GenericAPIView):
    """单客户信息操作"""
    # 拿到序列化器
    serializer_class = CustomerInfoSerializer
    # 拿到查询集
    queryset = CustomerInfo.objects.all()
    permission_classes = [IsAuthenticated]

    def get(self, request, pk):
        customer = self.get_object()
        serializer = self.get_serializer(instance=customer)
        return Response(data=serializer.data)

    def put(self, request, pk):
        role_name = request.user.roles.values_list('role_name', flat=True)
        if len(role_name) == 1 and role_name[0] == 'SA_User':
            return Response(data={"error": "普通用户不能修改客户"}, status=status.HTTP_403_FORBIDDEN)
        customer = self.get_object()
        serializer = self.get_serializer(instance=customer, data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        logger.info(f"{request.user} 修改客户 {serializer.validated_data['name']} 成功")
        return Response(data=serializer.validated_data, status=status.HTTP_200_OK)

    def delete(self, request, pk):
        role_name = request.user.roles.values_list('role_name', flat=True)
        if len(role_name) == 1 and role_name[0] == 'SA_User':
            return Response(data={"error": "普通用户不能删除客户"}, status=status.HTTP_403_FORBIDDEN)
        customer = self.get_object()
        customer.delete()
        logger.info(f"{request.user} 成功删除客户 {customer}")
        return Response(status=status.HTTP_204_NO_CONTENT)


class CustomerRegionChoicesAPIView(APIView):
    """专门获取 CustomerInfo 模型的 region choices 数据"""

    def get(self, request):
        region_choices = CustomerInfo._meta.get_field('region').choices
        # print(region_choices)
        # 推导式变成前端需要的格式
        options = [{'value': value, 'label': label} for value, label in region_choices]
        # return Response(data=region_choices)
        # print(options)
        return Response(data=options)

    """
    CustomerInfo._meta.get_field('region').choices 是 Django 模型系统中的一个高级用法，
    用于动态获取模型字段的 `choices` 选项。解释：

    CustomerInfo： Django 模型类。
    _meta`：Django 在模型类中自动添加的属性，是 `django.db.models.options.Options` 的实例，包含模型的所有元数据（如字段、索引、权限等）。
    get_field('region')：通过字段名获取该字段的 `Field` 对象（这里是 `CharField` 实例）。
    .choices：访问字段的 `choices` 属性，返回定义的可选项元组。
    """
